package com.dingreading.cloud.admin.service.impl;

import com.dingreading.cloud.admin.dto.SubjectsDto;
import com.dingreading.cloud.admin.entity.Subjects;
import com.dingreading.cloud.admin.entity.table.SubjectsTableDef;
import com.dingreading.cloud.admin.mapper.SubjectsMapper;
import com.dingreading.cloud.admin.service.SubjectsService;
import com.dingreading.cloud.admin.util.CdnUrlUtil;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.NepUtil;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class SubjectsServiceImpl extends BaseServiceImpl<SubjectsMapper, Subjects, SubjectsTableDef> implements SubjectsService {

    @Override
    protected SubjectsTableDef getTable() {
        return SubjectsTableDef.subjects;
    }

    @Resource
    private CdnUrlUtil cdnUrlUtil;


    @Override
    public List<Subjects> mainListByEnabled(Integer enabled) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.parentId.eq(0L));
        if (enabled != null)
            condition.and(table.enabled.eq(enabled));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.showOrder.asc());

        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public long duplicationSubjectMainName(Long id, String name) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.subjectName.eq(name));
        condition.and(table.parentId.eq(0L));
        if (id != null) {
            condition.and(table.id.ne(id));
        }
        return getMapper().selectCountByCondition(condition);
    }

    @Override
    public void updateSubjectMainIdAndNodes(Long id) {
        UpdateChain.of(Subjects.class)
                .set(table.subjectMainId, id)
                .set(table.nodes, "," + id + ",")
                .where(table.id.eq(id))
                .update();
    }

    @Override
    public int getMaxShowOrder() {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.parentId.eq(0L));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(QueryMethods.max(table.showOrder))
                .from(table)
                .where(condition);

        Integer integer = getMapper().selectObjectByQueryAs(wrapper, Integer.class);
        return NepUtil.nullToZero(integer);
    }

    @Override
    public boolean updateEnabledBySubjectMainId(Long subjectMainId, Integer enabled) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.subjectMainId.eq(subjectMainId));
        return UpdateChain.of(Subjects.class)
                .set(table.enabled, enabled)
                .where(condition)
                .update();
    }

    @Override
    public boolean updateEnabledByParentId(Long parentId, Integer enabled) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.id.eq(parentId).or(table.parentId.eq(parentId)));
        return UpdateChain.of(Subjects.class)
                .set(table.enabled, enabled)
                .where(condition)
                .update();
    }

    @Override
    public List<Subjects> getBySubjectMainId(Long subjectMainId) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (subjectMainId != null)
            condition.and(table.subjectMainId.eq(subjectMainId));
        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.levelIndex.asc(), table.showOrder.asc(), table.subjectOrder.asc());

        return getMapper().selectListByQuery(wrapper);
    }


    @Override
    public Integer getMaxSubjectOrderByPatentId(Long parentId) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.parentId.eq(parentId));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(QueryMethods.max(table.subjectOrder))
                .from(table)
                .where(condition);

        Integer integer = getMapper().selectObjectByQueryAs(wrapper, Integer.class);
        return NepUtil.nullToZero(integer);
    }


    @Override
    public Subjects getGtSubjectOrder(Long parentId, Integer subjectOrder) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.parentId.eq(parentId))
                .and(table.subjectOrder.gt(subjectOrder));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.subjectOrder.asc());

        return getMapper().selectOneByQuery(wrapper);
    }

    @Override
    public Subjects getLtSubjectOrder(Long parentId, Integer subjectOrder) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.parentId.eq(parentId))
                .and(table.subjectOrder.lt(subjectOrder));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.subjectOrder.desc());

        return getMapper().selectOneByQuery(wrapper);
    }

    @Override
    public void updateSubjectOrder(Long id, Integer orderNum) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.id.eq(id));

        UpdateChain.of(Subjects.class)
                .set(table.subjectOrder, orderNum)
                .where(condition)
                .update();
    }

    @Override
    public boolean updateLessonNum(Long id, int num) {
        return UpdateChain.of(Subjects.class)
                .set(table.lessonNum, num)
                .where(table.id.eq(id))
                .update();
    }

    @Override
    public R<Object> uploadInfo(
            String headStaffUid, String headStaffName, Long id,
            String bookIsbn, String bookPress, String bookImg
    ) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工uid为空");
        if (id == null)
            return R.fail("请选择子分类");
        if (
                StringUtils.isBlank(bookImg) && StringUtils.isBlank(bookIsbn) && StringUtils.isBlank(bookPress)
        ) return R.fail("请填写书籍信息");

        Subjects subjects = getMapper().selectOneByCondition(table.id.eq(id));
        if (subjects == null)
            return R.fail("子分类为空");
        if (subjects.getLevelEnd() != 1)
            return R.fail("子分类不是最后一层");

        boolean update = UpdateChain.of(Subjects.class)
                .set(table.bookIsbn, bookIsbn)
                .set(table.bookPress, bookPress)
                .set(table.bookImg, bookImg)
                .where(table.id.eq(id))
                .update();

        return update ? R.ok() : R.fail("信息添加失败");
    }

    @Override
    public R<Object> getSubjectDto(HttpServletRequest request, String headStaffUid, String headStaffName, Long id) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工uid为空");
        if (id == null)
            return R.fail("请选择学科信息");
        QueryWrapper wrapper = QueryWrapper.create()
                .where(table.id.eq(id));
        SubjectsDto subjects = getMapper().selectOneByQueryAs(wrapper, SubjectsDto.class);
        if (subjects == null)
            return R.fail("获取失败");

        if (StringUtils.isNotBlank(subjects.getBookImg())) {
            R<String> r = cdnUrlUtil.getCdnUrl(request, subjects.getBookImg());
            if (R.isError(r))
                return R.fail(r.getMsg());
            subjects.setBookImgCdnUrl(r.getData());
        }
        if (StringUtils.isNotBlank(subjects.getVideoUrl())) {
            R<String> r = cdnUrlUtil.getCdnUrl(request, subjects.getVideoUrl());
            if (R.isError(r))
                return R.fail(r.getMsg());
            subjects.setVideoCdnUrl(r.getData());
        }
        return R.ok(subjects);
    }

    @Override
    public Subjects getByUid(String subjectUid) {
        return getMapper().selectOneByCondition(table.uid.eq(subjectUid));
    }

    @Override
    public void updateNodes(Long id, String nodes) {
        UpdateChain.of(Subjects.class)
                .set(table.nodes, nodes)
                .where(table.id.eq(id))
                .update();
    }

    @Override
    public List<Subjects> listByMainIdAndLevelIndexAndNameIn(long mainId, int levelIndex, List<String> nameList) {
        QueryCondition condition = table.subjectMainId.eq(mainId)
                .and(table.levelIndex.eq(levelIndex))
                .and(table.subjectName.in(nameList));

        return getMapper().selectListByCondition(condition);
    }

    @Override
    public Subjects getByMainIdAndNameAndLevelIndex(long mainId, String name, int levelIndex) {
        QueryCondition condition = table.subjectMainId.eq(mainId)
                .and(table.subjectName.eq(name))
                .and(table.levelIndex.eq(levelIndex));

        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public List<Subjects> listByParentId(Long patentId) {
        QueryCondition condition = table.parentId.eq(patentId);
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<Subjects> listByParentIdIn(List<Long> patentIdList) {
        QueryCondition condition = table.parentId.in(patentIdList);
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public Subjects getByParentIdAndSubjectName(Long patentId, String subjectName, int levelIndex) {
        QueryCondition condition = table.parentId.eq(patentId)
                .and(table.subjectName.eq(subjectName))
                .and(table.levelIndex.eq(levelIndex));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public List<Subjects> listByVideoUrlIsNotNull() {
        return getMapper().selectListByCondition(table.videoUrl.isNotNull());
    }


}
